#ifndef _MODEL_H_
#define _MODEL_H_

#include "list.h"
#include "slab.h"
#include "datrie.h"
#include "result.h"
#include "context.h"

#define MODEL_SIZE_MAX	1024

#define	VIDX_BEG	0
#define	VIDX_END	1

//#define OOV_NR
//#define OOV_NS
//#define OOV_TR

enum	PUSH_TYPE{PUSH_TAG, PUSH_UNKNOWN, PUSH_CHAR};

typedef struct role{
	struct list_head	list;		//list head
	unsigned int		id;			//role id
	int					freq;		//freq
	struct role *		prev;	//viterbi prev
} role;

typedef struct edge{
	struct list_head	list;		//list head
	unsigned short		vidx_next;	//next vertex index
	int					freq;		//bifreq
} edge;

#define COLOR_WHITE	0
#define COLOR_GRAY	1
#define COLOR_BLACK	2

typedef struct vertex{
	struct list_head	list;		//list head
	struct list_head	top_list;	//top short order
	struct list_head	nr_list;	//role list
	struct list_head	ns_list;	//role list
	struct list_head	tr_list;	//role list
	struct list_head	edge_list;	//edge list
	unsigned short		off;		//offset
	unsigned short 		len;		//len
	unsigned short		vidx;		//index in vmap
	unsigned char		untype;		//untype state
	unsigned char		color;		//color for top sort
	int					freq;		//word freq
	int					rolei;		//tagi to TAG_ROLE
	int					ungrami;	//tagi to TAG_UNGRAM
} vertex;

typedef struct mod{
	slab *				slabp;					//slab
	result *			resp;					//result
	const dat *			datp;					//double array trie
	const ctx *			ctxp;					//context of untype
	const ctx *			nrp;
	const ctx *			nsp;
	const ctx *			trp;

	unsigned int		vnum;						//vertex num
	unsigned int		cnum;						//char num
	unsigned int		role_num;					//filtered num -- viterbi
	unsigned int	 	hsize;						//heap size -- kbest3
	struct list_head	graph[MODEL_SIZE_MAX];		//graph
	unsigned int		bitmap[MODEL_SIZE_MAX];		//vertex len bitmap of graph
	struct list_head	top;						//top sort order -- kbest2
	vertex *			vmap[MODEL_SIZE_MAX];		//vmap i to pointer
	unsigned char		closed[MODEL_SIZE_MAX];		//closed vertex -- kbest
	unsigned int 		dist[MODEL_SIZE_MAX];		//distance -- kbest
	unsigned short		prev[MODEL_SIZE_MAX];		//prev vertex -- kbest
	unsigned short 		ind[MODEL_SIZE_MAX];		//heap->vidx -- kbest3
	unsigned short 		map[MODEL_SIZE_MAX];		//vidx->heap -- kbest3
	unsigned short		role_off[MODEL_SIZE_MAX];	//filtered offset -- viterbi
	char				role_seq[MODEL_SIZE_MAX];	//best sequence -- viterbi
}mod;

mod * mod_new(slab * slabp, dat * datp, result * resp, ctx * ctxp, 
					ctx * nrp, ctx * nsp, ctx * trp);
int mod_free(mod * p);
int mod_push(mod * p, unsigned int off, unsigned short len,
				int var, enum PUSH_TYPE type);
int mod_set_cnum(mod * p, unsigned int off);
int mod_kbest(mod * p);
int oov(mod * p);
int mod_do(mod * p);
int mod_clear(mod * p);

#endif
